package cn.zebra.dev.mall.module.weixinPay.service.impl;

import cn.zebra.dev.mall.module.weixinPay.service.WeXinPayService;
import cn.zebra.dev.member.module.login.service.SecurityMemberService;
import cn.zebra.dev.net.local.utils.LocalNetUtils;
import cn.zebra.dev.order.module.item.service.OrdersItemService;
import cn.zebra.dev.order.module.order.constant.OrdersStatusConstant;
import cn.zebra.dev.order.module.order.entity.OrdersEntity;
import cn.zebra.dev.order.module.order.service.OrdersService;
import cn.zebra.dev.pay.module.wechat.entity.OrdersPayBillsEntity;
import cn.zebra.dev.pay.module.wechat.service.OrdersPayBillsService;
import cn.zebra.dev.utils.module.http.ssl.HttpClient;
import com.github.wxpay.sdk.WXPayUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayOutputStream;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;

@Service
public class WeXinPayServiceImpl implements WeXinPayService {

    @Value("${weixin.appid}")
    private String appid;         //微信公众账号或开放平台APP的唯一标识

    @Value("${weixin.mchid}")
    private String mchid;       //商户号

    @Value("${weixin.partnerkey}")
    private String partnerkey;    //商户密钥

    @Value("${weixin.apikey}")
    private String apikey;        //api秘钥

    @Value("${weixin.url}")
    private String url;           //统一下单接口

    @Value("${weixin.notifyurl}")
    private String notifyurl;     // 回调地址

    @Autowired
    private OrdersService ordersService;

    @Autowired
    private SecurityMemberService securityMemberService;

    @Autowired
    private OrdersPayBillsService ordersPayBillsService;

    @Autowired
    private OrdersItemService ordersItemService;

    @Override
    public Map<String, String> prepay(Long orderId, HttpServletRequest request) throws Exception {
        //校验订单信息
        OrdersEntity ordersEntity = ordersService.findById(orderId);
        if (ordersEntity == null) {
            throw new RuntimeException("订单不存在!");
        }
        if (ordersEntity.getOrdersStatus() != OrdersStatusConstant.PENDING_PAYMENT) {
            throw new RuntimeException("订单状态不正确");
        }
        //封装需要的传入的参数
        Map<String, String> data = new HashMap<>();
        //应用ID
        data.put("appid", appid);
        //商户号
        data.put("mch_id", mchid);
        //随机字符串
        data.put("nonce_str", WXPayUtil.generateNonceStr());
        //商品描述
        data.put("body", ordersEntity.getOrdersTitle());
        //商户订单号
        data.put("out_trade_no", ordersEntity.getOrdersSn());
        //标价金额
        data.put("total_fee", ordersItemService.findByOrderId(ordersEntity.getId()).toString());
        //终端IP
        data.put("spbill_create_ip", LocalNetUtils.getLocalIp());
        //通知地址
        data.put("notify_url", notifyurl);
        //交易类型:JS_API=公众号支付，NATIVE=扫码支付，APP=app支付
        data.put("trade_type", "APP");
        //生成带有签名的字符串
        String sign = WXPayUtil.generateSignedXml(data, apikey);
        data.put("sign", sign);
        String xmlData = WXPayUtil.mapToXml(data);
        //向微信发起预支付
        HttpClient httpClient = new HttpClient(url);
        //请求参数
        httpClient.setXmlParam(xmlData);
        httpClient.setHttps(true);
        httpClient.post();
        String strXML = httpClient.getContent();
        Map<String, String> map = WXPayUtil.xmlToMap(strXML);
        //封装参数返回
        Map<String, String> result = new HashMap<>();
        result.put("appid", appid);
        result.put("partnerid", mchid);
        result.put("prepayid", map.get("prepay_id").toString());
        result.put("noncestr", WXPayUtil.generateNonceStr());
        result.put("package", "Sign=WXPay");
        //返回给App端的数据进行签名
        result.put("sign", WXPayUtil.generateSignedXml(result, apikey));
        return result;
    }

    @Override
    public void notifyUrl(HttpServletRequest request, HttpServletResponse response) throws Exception {
        //微信支付系统调用方法（发送支付的结果）
        ServletInputStream is = request.getInputStream();
        //解析流对象获取数据（内存级别操作）
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        //定义缓冲区间
        byte[] bytes = new byte[1024];
        int len = 0;
        while ((len = is.read(bytes)) != -1) {
            bos.write(bytes, 0, len);
        }
        bos.flush();
        bos.close();
        is.close();
        //获取微信回调数据(将数据转成String)
        String strXml = new String(bos.toByteArray(), "UTF-8");
        System.out.println("通知结果为：" + strXml);
        //回调的数据
        Map<String, String> map = WXPayUtil.xmlToMap(strXml);
        if (map.get("result_code") != null && "SUCCESS".equals(map.get("result_code"))) {
            //成功，获取实际支付钱数
            String totalFee = map.get("total_fee");
            //获取订单号
            String outTradeNo = map.get("out_trade_no");
            //获取订单流水号
            String transactionId = map.get("transaction_id");
            //修改订单状态
            OrdersEntity ordersEntity = ordersService.findByOrderNo(outTradeNo);
            ordersService.updateOrderStatusById(ordersEntity.getId(), OrdersStatusConstant.PAYMENT_RECEIVED);
            OrdersPayBillsEntity entity = new OrdersPayBillsEntity();
            entity.setOrderId(ordersEntity.getId());
            entity.setShopId(ordersEntity.getShopId());
            entity.setOutTradeNo(outTradeNo);
            entity.setPayAmount(new BigDecimal(totalFee));
            entity.setUserId(securityMemberService.getMemberId());
            entity.setPayTime(LocalDateTime.now());
            entity.setTransactionId(transactionId);
            if (!ordersPayBillsService.save(entity)) {
                throw new RuntimeException("保存账单失败");
            }
        }
    }

    /**
     * @param ordersSn 订单号
     * @return java.util.Map<java.lang.String, java.lang.String>
     * @Description 查询订单的支付状态
     * @Date 10:28 2020/4/27
     **/
    @Override
    public Map<String, String> findByPayStatus(String ordersSn) {
        try {
            //查询订单地址
            String url = "https://api.mch.weixin.qq.com/pay/orderquery";
            //封装支付接口需要的数据
            HashMap<String, String> data = new HashMap<>();
            data.put("appid", appid);             //appid
            data.put("mch_id", mchid);          //商户号
            data.put("out_trade_no", ordersSn);   //商户订单号
            data.put("nonce_str", WXPayUtil.generateNonceStr());   //随机字符串
            String xmlParam = WXPayUtil.generateSignedXml(data, partnerkey);
            //创建Httpclient发送请求
            HttpClient httpClient = new HttpClient(url);
            httpClient.setXmlParam(xmlParam);   // 请求参数
            httpClient.setHttps(true);
            httpClient.post();
            // 获取响应的数据
            String strXML = httpClient.getContent();
            Map<String, String> map = WXPayUtil.xmlToMap(strXML);
            return map;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
}
